<?php
/**
 * 同城微聚汇 微信支付插件
 * ============================================================================
 * 版权所有 2015-2027 武汉鼎联信息技术有限公司，并保留所有权利。
 * 网站地址: http://dlshop.dliansoft.com
 * ----------------------------------------------------------------------------
 * 这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和使用 .
 * 不允许对程序代码以任何形式任何目的的再发布。
 * ============================================================================
 * Author: IT宇宙人
 * Date: 2015-09-09
 */

use think\Model;
/**
 * API 参数
 * @var array
 * 'mch_appid'         # 公众号APPID
 * 'mchid'             # 商户号
 * 'device_info'       # 设备号
 * 'nonce_str'         # 随机字符串
 * 'partner_trade_no'  # 商户订单号
 * 'openid'            # 收款用户openid
 * 'check_name'        # 校验用户姓名选项 针对实名认证的用户
 * 're_user_name'      # 收款用户姓名
 * 'amount'            # 付款金额
 * 'desc'              # 企业付款描述信息
 * 'spbill_create_ip'  # Ip地址
 * 'sign'              # 签名
 */

class bill extends Model
{
    public $tableName = 'plugin'; // 插件表
    public $parameters = [];



    /**
     * 析构流函数
     */
    public function  __construct()
    {
        parent::__construct();

        require_once("lib/WxPay.Api.php"); // 微信扫码支付demo 中的文件
        require_once("example/WxPay.NativePay.php");
        require_once("example/WxPay.JsApiPay.php");

        $this->url = 'https://api.mch.weixin.qq.com/pay/downloadbill';
        $this->curl_timeout = '6';
        $paymentPlugin = M('Plugin')->where("code='weixin' and  type = 'payment' ")->find(); // 找到微信支付插件的配置
        $config_value = unserialize($paymentPlugin['config_value']); // 配置反序列化

        WxPayConfig::$appid = $config_value['appid']; // * APPID：绑定支付的APPID（必须配置，开户邮件中可查看）
        WxPayConfig::$mchid = $config_value['mchid']; // * MCHID：商户号（必须配置，开户邮件中可查看）
        WxPayConfig::$key = $config_value['key']; // KEY：商户支付密钥，参考开户邮件设置（必须配置，登录商户平台自行设置）
        WxPayConfig::$appsecret = $config_value['appsecret']; // 公众帐号secert（仅JSAPI支付的时候需要配置)，
    }


    /**
     *     作用：使用证书，以post方式提交xml到对应的接口url
     */
    public function postXmlSSLCurl($xml, $second = 30)
    {
        $ch = curl_init();
        //超时时间
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch, CURLOPT_URL, $this->url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        $data = curl_exec($ch);
        //返回结果
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            echo "curl出错，错误码:$error" . "
";
            echo "错误原因查询
";
            curl_close($ch);
            return false;
        }
    }

    /**
     * 对账单
     */
    public function transfer($data)
    {
        $input['appid'] = WxPayConfig::$appid;
        $input['mch_id'] = WxPayConfig::$mchid;
        $input['nonce_str'] = $this->randString();
        $input['bill_date'] = $data;
        $input['bill_type'] = 'ALL';
        $sign = $this->SetSign($input);
        $input['sign'] = $sign;
        $xml = $this->ToXml($input);
        $response = $this->postXmlSSLCurl($xml);

        $arr = explode(Chr(13),$response);

        unset($arr[0]);//删除第一个
        $count = count($arr);
        unset($arr[$count]);
        unset($arr[$count-1]);
        unset($arr[$count-2]);//删除不需要储存的数据

        foreach($arr as $k=>$v){
            $str = str_replace(',','',$v);
            $str_arr[] = explode('`',$str);
        }
        if($str_arr){
            foreach($str_arr as $k=>$v){
                $add[$k]['tradetime'] = $v[1];
                $add[$k]['ghid'] = $v[2];
                $add[$k]['mchid'] = $v[3];
                $add[$k]['submch'] = $v[4];
                $add[$k]['deviceid'] = $v[5];
                $add[$k]['wxorder'] = $v[6];
                $add[$k]['bzorder'] = $v[7];
                $add[$k]['openid'] = $v[8];
                $add[$k]['tradetype'] = $v[9];
                $add[$k]['tradestatus'] = $v[10];
                $add[$k]['bank'] = $v[11];
                $add[$k]['currency'] = $v[12];
                $add[$k]['totalmoney'] = $v[13];
                $add[$k]['redpacketmoney'] = $v[14];
                $add[$k]['productname'] = $v[15];
                $add[$k]['bzdatapacket'] = $v[16];
                $add[$k]['fee'] = $v[17];
                $add[$k]['rate'] = $v[18];
            }
            $retime = strtotime($data);
            $time = date('Y-m-d',$retime);
            $where['tradetime'] = array('like',"%$time%");
            $bill = M('wx_bill')->where($where)->select();
            if(empty($bill)){
                foreach($add as $v){
                   $re = M('wx_bill')->add($v);
                }
                if($re){
                    return '3';
                }else{
                    return '2';
                }
            }else{
                return '1';
            }
        }else{
            return '4';
        }
    }


    /**
     * 随机9位数字符串
     * @return string
     */
    public function randString()
    {
        $metas = range(0, 9);
        $metas = array_merge($metas, range('A', 'Z'));
        $metas = array_merge($metas, range('a', 'z'));
        $str = '';
        for ($i = 0; $i < 15; $i++) {
            $str .= $metas[rand(0, count($metas) - 1)];
        }
        return $str;
    }


    //生成签名
    public function SetSign($data)
    {
        $sign = $this->MakeSign($data);
        return $sign;
    }


    /**
     * 生成签名
     * @return 签名，本函数不覆盖sign成员变量，如要设置签名需要调用SetSign方法赋值
     */
    public function MakeSign($data)
    {
        //签名步骤一：按字典序排序参数
        ksort($data);
        $string = $this->ToUrlParams($data);
        //签名步骤二：在string后加入KEY
        $string = $string . "&key=" . WxPayConfig::$key;
        //签名步骤三：MD5加密
        $string = md5($string);
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }


    /**
     * 格式化参数格式化成url参数
     */
    public function ToUrlParams($data)
    {
        $buff = "";
        foreach ($data as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff;
    }


    /**
     * 输出xml字符
     * @throws WxPayException
     **/

    public function ToXml($data)
    {
        if (!is_array($data) || count($data) <= 0) {
            throw new WxPayException("数组数据异常！");
        }
        $xml = "<xml>";
        foreach ($data as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }


    public function object2array($object){
        if (is_object($object)) {
            foreach ($object as $key => $value) {
                $array[$key] = $value;
            }
        }
        else {
            $array = $object;
        }
        return $array;
    }
}